package org.NooLab.itexx.retrieval;

import org.NooLab.itexx.ITexxWindowIntf;
import org.NooLab.itexx.stuctures.RequestHistory;
import org.NooLab.itexx.stuctures.RequestItem;

import org.NooLab.utilities.logging.PrintLog;

public class SearchRequestHandler
                                       extends
                                       				SearchRequestAbstract
                                       implements
                                       				SearchRequestIntf{

       
       
        boolean manualRequest = false;
        boolean isWaitingForStartingNextRetrieval=false ;
        boolean dispatcherIsRunning = false;
        private boolean startRetrieval=false;
       
        transient private Dispatcher dispatcher;
        transient private Thread retrievalDispatchThrd;
       
        transient RequestItem dedicatedRequest;
        RequestHistory requestHistory ;
        
        private RequestHistory localRequestHistory = new RequestHistory();
       
        boolean dispatcherConfirmed = false;
        transient PrintLog out = new PrintLog(2,false);

       
       
        // ========================================================================
        public SearchRequestHandler(ITexxWindowIntf texxWindowApp){
                super(texxWindowApp);
       
               
                requestHistory = texxWindowApp.getAppCommons().getSessionManager().getHistory() ;
                							out.print(2, "SearchRequestHandler, creating Dispatcher (1)...");
                dispatcher = new Dispatcher();
        }
        // ========================================================================
       
       
        public void close(){

                isWaitingForStartingNextRetrieval=false ;
                dispatcherIsRunning = false;

                out.delay(300) ;
        }


       
        public void updateRequestEntries( RetrievalEngine engine, RequestItem request ) {
               
        									out.printErr(3, "\n>>>>>>>>>>        SearchRequestHandler Object = "+this.toString()+"   \n" );

                if ((engine==null) || (request==null) ){
                        return;
                }
               
                String requeststr = request.getRequestStr() ;
               
                dedicatedRequest = request ;
               
                dedicatedRequest.setEngine(engine) ;
                // first put it to the local list !!
                getLocalRequestHistory().add(0,dedicatedRequest) ; 
                							out.printErr(3, "dispatcher is running (1): "+dispatcherIsRunning);
                							out.print(3, "request added to local queue (n="+getLocalRequestHistory().size()+"...");
                							out.printErr(3, ">>>>>>>>>>        list object (1): "+getLocalRequestHistory().toString());
                testForDispatcher();
                // dispatcher.a=3;
                if (dispatcherIsRunning == false){
                	if (dispatcher!=null){
                		dispatcher=null ;
                	}
                }
                							out.printErr(3, "dispatcher is running (2): "+dispatcherIsRunning);

                							
                if ((dispatcherIsRunning == false) || (dispatcher==null) ||
                        (retrievalDispatchThrd==null) || (retrievalDispatchThrd.isAlive()==false) || (retrievalDispatchThrd.isInterrupted()==true)){
                							out.print(3, "SearchRequestHandler, creating Dispatcher (2)...");
                	dispatcher = new Dispatcher(); out.delay(60); 
                }
                							out.printErr(3, "dispatcher is running (3): "+dispatcherIsRunning);
                if (manualRequest==false){
                        dispatcherConfirmed = false;
                        // startRetrieveDelayTimer(); // ??
                        out.delay(500);
                        startRetrieval=true;
                }else{
                       
                        dispatcherConfirmed = false;
                        startRetrieval = true;
                        //start a supervisor here... which waits 2 seconds
                        int z=0;
                        while ((z<200) && (dispatcherConfirmed == false)){
                                z++;
                                out.delay(10);
                        }
                        if (dispatcherConfirmed == false){
                        					out.print(3, "SearchRequestHandler, creating Dispatcher (3)...");
                                dispatcher = new Dispatcher();
                                if (localRequestHistory.size()==0){
                                        localRequestHistory.add(0,dedicatedRequest) ;
                                }
                        }
                }
        }
       
        private void testForDispatcher() {
			// 
        	boolean tested=false;
        	int iCount1 ,iCount2;
        	
        	if (dispatcher==null){
        		dispatcherIsRunning=false;
        		return;
        	}
        	
        	while ((tested==false)){
        		
        		iCount1 = dispatcher.icount;
        		out.delay( dispatcher.dispatcherDelay+100 );
        		iCount2 = dispatcher.icount;
        		out.delay( 10 );
        		if ((iCount1<iCount2)){
        			dispatcherIsRunning=true;	
        			break;
        		}
        		if ((iCount1==iCount2)){
        			dispatcherIsRunning=false;
        			break;
        		}
        	}
			
		}
		private void startRetrieveDelayTimer() {
               
                if (isWaitingForStartingNextRetrieval){
                        isWaitingForStartingNextRetrieval=false;
                        out.delay(50) ;
                }
                new RetrievalTimer();
               
        }

       
        public RequestHistory getLocalRequestHistory() {
			return localRequestHistory;
		}


		class RetrievalTimer implements Runnable{
               
                Thread retrievTimerThrd;
               
               
                public RetrievalTimer (){
                        retrievTimerThrd = new Thread(this,"retrievTimerThrd") ;
                        retrievTimerThrd.start() ;
                }

                @Override
                public void run() {
                        isWaitingForStartingNextRetrieval = true;
                        int z=0;
                       
                        while ((z<100) && (isWaitingForStartingNextRetrieval)){
                                out.delay(10);
                                z++;
                                if (manualRequest){
                                        break;
                                }
                        }
                       
                       
                        // start retrieval via callback
                        if (isWaitingForStartingNextRetrieval){
                                if ((z >= 99) || (manualRequest)) {
                                       
                                        startRetrieval = true;
                                }
                        }
                       
                       
                        manualRequest = false;
                        isWaitingForStartingNextRetrieval=false;
                       
                }
               
               
               
               
        }

		class Dispatcher implements Runnable {

			public int a = 0;
			public int icount = 0;
			private int dispatcherDelay = 300;

		public Dispatcher() {
			retrievalDispatchThrd = new Thread(this, "retrievalDispatchThrd");
			retrievalDispatchThrd.start();
		}

		public void close() {
			// 
			
		}

		@Override
		public void run() {

			int lrh = 0 ;
			dispatcherIsRunning = true;
			boolean isWorking = false;
			RequestItem request;
			
											out.print(3, "\nSearchRequestHandler::Dispatcher process has been started.\n");

			while (dispatcherIsRunning) {

				
				icount++;
				lrh = getLocalRequestHistory().size();
											if (lrh > 0) {
												out.print(4, "number of waiting requests : " + lrh);
											}
											if ((a>0) || (startRetrieval)){
												out.printErr(3, ">>>>>>>>>>        list object (2): "+getLocalRequestHistory().toString());
												a--;
											}
				if ((isWorking == false) && (startRetrieval) && (lrh > 0)) {
					isWorking = true;
											out.printErr(3, ">>>>>>>>>>        list object: "+getLocalRequestHistory().toString());
					dispatcherConfirmed = true;
					request = getLocalRequestHistory().get(0);
											out.print(2, "request scheduled, now exerting..." );
					getLocalRequestHistory().remove(0);
					request.perform();

					

					isWorking = false;
					if (localRequestHistory.size() == 0) {
						startRetrieval = false;
					}
				}
				if (icount>1000){
					dispatcherIsRunning=false; 
					// we stop the process by itself ... auto-removal after 400 seconds
				}
				out.delay(dispatcherDelay);
				
			}// dispatcherIsRunning ->

											out.printErr(2,"\nSearchRequestHandler::Dispatcher process has been stopped.\n");
			dispatcherIsRunning = false;
			startRetrieval = false;

		}

	}

        public boolean isManualRequest() {
                return manualRequest;
        }

        public void setManualRequest(boolean manualRequest) {
                this.manualRequest = manualRequest;
        }

        public boolean isWaitingForStartingNextRetrieval() {
                return isWaitingForStartingNextRetrieval;
        }




        public RequestHistory getRequestHistory() {
                return requestHistory;
        }




        public void setRequestHistory(RequestHistory requestHistory) {
                this.requestHistory = requestHistory;
        }




        public boolean isDispatcherIsRunning() {
                return dispatcherIsRunning;
        }




        public void setDispatcherIsRunning(boolean dispatcherIsRunning) {
                this.dispatcherIsRunning = dispatcherIsRunning;
        }




        public void setWaitingForStartingNextRetrieval(boolean isWaitingForStartingNextRetrieval) {
                this.isWaitingForStartingNextRetrieval = isWaitingForStartingNextRetrieval;
        }
}
